home *** CD-ROM | disk | FTP | other *** search
- Submitted-by: uunet!mcvax!philmds!leo (Leo de Wit)
- Posting-number: Volume 1, Issue 70
- Archive-name: scroll
-
- The following program, when placed in the AUTO folder, speeds up scrolling
- (BIOS output only). Difference is most noticeable with relative few chars
- per line; speeds up full screen editors, 'more' utilities, etc.
- For all resolutions; not for GEM, only for TOS.
- The corresponding binary is sent to the moderator of comp.binaries.atari.st.
- The program was assembled and linked with the assembler and linker from the
- GST-C compiler.
-
- For correspondence conceirning this program (bugs, questions etc.) try
-
- L. J. M. de Wit
- Nachtegaallaan 7
- 5731XP Mierlo
- Holland
- e-mail: ..!mcvax!philmds!leo
-
- ------------------------ s t a r t h e r e ---------------------------------
- ******************************************************************************
- * *
- * scroll.asm version 1.0 of 23 July 1988 (C) L.J.M. de Wit 1988 *
- * *
- * This software may be used and distributed freely if not used commercially *
- * and the originator (me) is mentioned. *
- * *
- ******************************************************************************
- *
- * NAME
- * scroll - fast text scrolling
- *
- * SYNTAX
- * scroll.prg
- *
- * DESCRIPTION
- * Scroll provides for fast scrolling; this is achieved by using a 64K
- * buffer for screen memory and changing the physical screen location therein.
- * The actual changes take place at the receipt of certain escape codes or
- * characters that would make the entire display scroll.
- *
- * Scroll should be in the AUTO folder as SCROLL.PRG so that it is
- * installed memory resident when the system is loaded.
- *
- * DECISIONS
- * The extra storage needed grabs a 33K from your free mem, unless
- * the memory cannot be reserved adjacent to the original screen memory,
- * in which case 65K is needed.
- * The console output vector at 4a8 is used to trap the escape codes.
- * Also the bios vector had to be changed (a pity);
- * this is only needed to be able to load from AUTO folders:
- * the con_state vector is reinitiated when the resolution changes
- * The program must reside in the current drive's AUTO folder to be able
- * to find itself.
-
- module scroll
- section s.ccode
-
- * character codes
- lf equ 10
- vt equ 11
- ff equ 12
- cr equ 13
- esc equ 27
-
- * scrinfo offsets
- maxcol equ 0
- maxrow equ 2
- bprow equ 4
- scrad equ 10
- col equ 16
- row equ 18
- flag equ 38
-
- * system variables
- v_bas_ad equ $44e
- con_state equ $4a8
-
- * GEMDOS & (X)BIOS stuff
- gemdos equ 1
- bios equ 13
- xbios equ 14
- ptermres equ $31
- supexec equ 38
- setexc equ 5
- setscreen equ 5
- physbase equ 2
- setblock equ $4a
- pexec equ $4b
-
- * divers
- bpaglen equ $100
- textlen equ 12
- datalen equ 20
- bsslen equ 28
- linea0 equ $a000
-
- scrinit
- move.l 4(sp),a3 * basepage start
- move.l #bpaglen,d3 * base page length
- add.l textlen(a3),d3 * + text length
- add.l datalen(a3),d3 * + data length
- add.l bsslen(a3),d3 * + bss length
- add.l #256,d3 * + rounding length
- move.w #physbase,-(sp)
- trap #xbios
- addq.l #2,sp
- move.l d0,a4 * Start physical screen memory
- dc.w linea0
- suba.w #44,a0
- lea.l scrinfo(pc),a1
- move.l a0,(a1) * start screen info to scrinfo
- move.l a0,a2 * and also a2
- move.w maxrow(a2),d1
- addq.l #1,d1
- mulu.w bprow(a2),d1 * screen size into d1
- lea.l 8(sp),a0
- cmpa.l a4,a0
- bne.s scrinstall * last location not start of phys. screen mem.
- tst.b 128(a3)
- bne.s scrinstall * Prog. had argument: called the second time
- add.l d1,d3 * add a screen size
- sub.l d3,a0 * this will be taken off current prog area
- move.l a0,sp
- suba.l a3,a0
- move.l a0,-(sp)
- move.l a3,-(sp)
- move.w #0,-(sp)
- move.w #setblock,-(sp)
- trap #gemdos * Leaving just enough for next load of myself
- lea.l 12(sp),sp
- pea nullstr
- pea argstr
- pea progname
- move.w #0,-(sp)
- move.w #pexec,-(sp)
- trap #gemdos * load & exec myself with a nonzero arglist
- lea.l 12(sp),sp
- clr.w -(sp)
- trap #gemdos * finished
-
- scrinstall
- lea.l 8(sp),a0
- cmpa.l a4,a0
- bne.s notattop * current mem not adjacent to phys. screen mem.
- attop
- suba.l a3,a0
- move.l a0,d3 * d3 : just all we've got
- lea.l topbase(pc),a0
- move.l a4,(a0) * current phys screen mem becomes top base
- sub.l d1,a4
- lea.l botbase(pc),a0 * and botbase a screen 'lower'
- move.l a4,(a0)
- bra.s endcalc
- notattop
- move.l a3,d0
- add.l d3,d0
- clr.b d0 * Adjust for 256 byte boundary
- lea.l botbase(pc),a0
- move.l d0,(a0) * address lowest screen
- add.l d1,d0 * a screen 'higher'
- lea.l topbase(pc),a0
- move.l d0,(a0) * address highest screen
- add.l d1,d3 * add a screen's length to mem needed
- add.l d1,d3 * and another one
- endcalc
- pea setvect(pc)
- move.w #supexec,-(sp)
- trap #xbios * set new console output vector
- addq.l #6,sp
- pea newbios(pc)
- move.w #$2d,-(sp)
- move.w #setexc,-(sp)
- trap #bios * Set new BIOS vector
- addq.l #8,sp
- lea.l oldbios(pc),a0
- move.l d0,(a0) * Save old one
- move.l topbase(pc),d0
- move.w #-1,-(sp)
- move.l d0,-(sp)
- move.l d0,-(sp)
- move.w #setscreen,-(sp)
- trap #xbios * make highest screen current
- lea.l 12(sp),sp
- clr.w -(sp) * return value: 0 for success
- move.l d3,-(sp) * # bytes to keep
- move.w #ptermres,-(sp) * keep process
- trap #gemdos * stops here...
-
- * New bios routine; only sets con_state to point to newconsole if not already
- * saving the old value.
- newbios
- lea.l newconsole(pc),a0
- cmpa.l con_state,a0
- beq.s newsame
- bsr setvect * Set con_state if it was not newconsole
- newsame
- movea.l oldbios(pc),a0
- jmp (a0)
-
- * This is the routine that con_state will always point to, except
- * when printing characters from within the routine itself.
- newconsole
- move.l cvsav(pc),con_state * restore original vector
- move.w d1,-(sp) * save character to be printed on the stack
- movea.l scrinfo(pc),a1
- lea.l hadesc(pc),a0
- tst.b (a0)
- beq.s noesc * If previous char was not escape; else ...
- sf.b (a0) * Reset escape flag
- tst.w row(a1)
- bne.s no_0row * If cursor not on row 0
- cmp.w #'I',d1
- bne.s not_i * If not ESC I
- bsr scr_down * else scroll down
- move.w #esc,d1
- bsr charout * and print the ESC
- move.w #'I',d1
- bsr charout * and the I
- bra newdone
- not_i
- cmp.w #'L',d1
- bne.s not_l * If not ESC L
- bsr scr_down * else scroll down
- move.w #esc,d1
- bsr charout * and print the ESC
- move.w #'H',d1
- bsr charout * and a H (cursor home)
- bra.s newdone
- not_l
- cmp.w #'M',d1
- bne.s no_0row * If not ESC M
- move.w #cr,d1
- bsr charout * else print CR
- move.w #lf,d1
- bsr charout * and LF
- bsr.s scr_up * and scroll up
- bra.s newdone
- no_0row
- move.w #esc,d1 * In all other 'escape cases'
- bsr charout * print the ESC
- move.w (sp),d1
- bsr charout * and the current character
- bra.s newdone
- noesc
- cmp.w #esc,d1 * Is current char an ESC?
- bne.s nonesc
- lea.l hadesc(pc),a0
- st (a0) * Mark the flag for 'had escape'
- bra.s newdone
- nonesc
- move.w maxrow(a1),d0
- cmp.w row(a1),d0
- bne.s newrest * If not yet at bottom row of display
- cmp.w #lf,d1
- beq.s newup * But else: If you had a LF
- cmp.w #vt,d1
- beq.s newup * or a VT
- cmp.w #ff,d1
- beq.s newup * or a FF
- cmp.w #' ',d1
- blt.s newrest * or: a printing character
- move.w maxcol(a1),d0
- cmp.w col(a1),d0
- bne.s newrest * and cursor at last column
- btst #3,flag(a1)
- beq.s newrest * and auto wrap mode; then:
- newup
- bsr.s scr_up * scroll up
- newrest
- move.w (sp),d1 * Print the character saved
- bsr charout
- newdone
- addq.l #2,sp * Clean up stack
- bsr setvect * Reset con_state to point to me again
- rts
-
- * Scroll up routine
- * Depending on current base position the new screen location is only reset
- * or there is an area copy as well.
- scr_up
- movea.l scrinfo(pc),a1
- move.w bprow(a1),d0
- movea.l v_bas_ad,a0
- cmpa.l topbase(pc),a0
- bge.s up_istop
- adda.w d0,a0 * If not at top address, simply add a row's
- move.l a0,-(sp) * size to the current address
- bsr newscreen * and make that the current
- addq.l #4,sp
- bra.s up_end
- up_istop
- move.w maxrow(a1),d1
- mulu.w d0,d1
- move.l botbase(pc),a2
- move.l a2,-(sp) * Save copy of botbase on stack
- adda.w d0,a0
- move.l a2,a1
- suba.l a0,a1 * Difference into a1
- move.l a1,-(sp) * Save it.
- move.w d1,-(sp) * # bytes to be copied: all but one row
- move.l a2,-(sp) * destination: botbase
- move.l a0,-(sp) * source: current address + one row size
- bsr moevmem * copy it
- lea.l 10(sp),sp
- move.l (sp)+,d0 * Difference into d0
- movea.l scrinfo(pc),a1
- add.l d0,scrad(a1) * Make up for the moevmem for cursor scrad
- bsr newscreen * Make botbase start of new screen
- addq.l #4,sp
- up_end
- movea.l scrinfo(pc),a1
- sub.w #1,row(a1) * Decrement row #
- move.w maxrow(a1),d0
- mulu.w bprow(a1),d0
- move.l v_bas_ad,a0
- adda.w d0,a0
- move.l a0,-(sp)
- bsr.s clearline * Clear last row of display
- addq.l #4,sp
- rts
-
- scr_down
- movea.l scrinfo(pc),a1
- move.w bprow(a1),d0
- movea.l v_bas_ad,a0
- cmpa.l botbase(pc),a0
- ble.s do_istop * If current screen already at top
- suba.w d0,a0 * Else simply subtract a row's
- move.l a0,-(sp) * size from the current address
- bsr.s newscreen * and make that the current
- addq.l #4,sp
- bra.s do_end
- do_istop
- move.w maxrow(a1),d1
- mulu.w d0,d1
- move.l topbase(pc),a2
- move.l a2,-(sp) * Save copy of topbase on stack
- adda.w d0,a2
- move.l a2,a1
- suba.l a0,a1 * Difference into a1
- move.l a1,-(sp) * Save it.
- move.w d1,-(sp) * # bytes to be copied: all but one row
- move.l a2,-(sp) * destination: topbase + one row size
- move.l a0,-(sp) * source: current address
- bsr.s moevmem * copy it
- lea.l 10(sp),sp
- move.l (sp)+,d0 * Difference into d0
- movea.l scrinfo(pc),a1
- add.l d0,scrad(a1) * Make up for the moevmem for cursor scrad
- bsr.s newscreen * Make botbase start of new screen
- addq.l #4,sp
- do_end
- movea.l scrinfo(pc),a1
- add.w #1,row(a1) * Increment row #
- move.l v_bas_ad,-(sp)
- bsr.s clearline * Clear top row of display
- addq.l #4,sp
- rts
-
- clearline
- movea.l scrinfo(pc),a0
- moveq.l #0,d0
- move.w bprow(a0),d0 * # : bytes per row
- asr.w #4,d0 * / 16 doing 4 longs at a time
- subq.l #1,d0
- move.l 4(sp),a0 * Memory start address of row
- moveq.l #0,d1 * Filler
- clrnxt
- move.l d1,(a0)+
- move.l d1,(a0)+
- move.l d1,(a0)+
- move.l d1,(a0)+
- dbra d0,clrnxt
- rts
-
- setvect
- lea.l cvsav(pc),a0
- move.l con_state,(a0) * Save current con_state value
- lea.l newconsole(pc),a0
- move.l a0,con_state * and make it newconsole for now
- rts
-
- newscreen
- move.l 4(sp),d0 * New start address of display
- move.l d0,v_bas_ad * into logical screen pointer
- swap d0
- move.b d0,$ffff8201 * and also
- swap d0
- lsr.w #8,d0
- move.b d0,$ffff8203 * into physical screen pointer
- rts
-
- charout
- and.w #$ff,d1 * For printing
- move.l con_state,a0 * from within newconsole
- jmp (a0)
-
- moevmem
- move.l 4(sp),a0 * Source address
- move.l 8(sp),a1 * Destination address
- move.w 12(sp),d0 * #
- lea.l (a0,d0.w),a2 * End of source area
- cmpa.l a1,a0
- bge.s first
- cmpa.l a2,a1
- blt.s second
- first
- lsr.w #4,d0 * /16, copying 4 longs at a time
- sub.w #1,d0
- f_next
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- dbra d0,f_next * Copy source to destination, forwards
- rts
- second
- lea.l (a1,d0.w),a1 * End address of dest area
- lsr.w #4,d0 * /16, copying 4 longs at a time
- sub.w #1,d0
- s_next
- move.l -(a2),-(a1)
- move.l -(a2),-(a1)
- move.l -(a2),-(a1)
- move.l -(a2),-(a1)
- dbra d0,s_next * Copy source to destination, backwards
- rts
-
- section s.data
-
- oldbios dc.l 0 * Old bios vector
- cvsav dc.l 0 * For saving con_state vector
- scrinfo dc.l 0 * (Copy of) screen info pointer
- botbase dc.l 0 * Ptr to lowest screen used
- topbase dc.l 0 * Ptr to highest screen used
- nullstr dc.l 0
- argstr dc.b 6,'second'
- progname dc.b '\AUTO\SCROLL.PRG',0
- hadesc dc.b 0 * Boolean: Was previous char an escape?
-
- end
-
-
-